#pragma once
#include <iostream>
#include <string>
#include <memory>
#include <unordered_map>
#include "Connection.hpp"
#include "Epoller.hpp"

//  对链接的管理 增删查改
class Reactor
{
    const static int size = 128;

private:
    bool IsExist(std::shared_ptr<Connection> &conn)
    {
        auto iter = _connections.find(conn->Sockfd());
        return iter != _connections.end();
    }
    bool IsExist(int sockfd)
    {
        return _connections.find(sockfd) != _connections.end();
    }

    void LoopOnce(int timeout)
    {
        int n = _epoller->Wait(revs, size, timeout);
        for (int i = 0; i < n; i++)
        {
            int sockfd = revs[i].data.fd;
            uint32_t events = revs[i].events;

            if (events & EPOLLHUP)
                events = (EPOLLIN | EPOLLOUT); // 统一报错
            if (events & EPOLLERR)
                events = (EPOLLIN | EPOLLOUT); // 统一报错
            if ((events & EPOLLIN) && IsExist(sockfd))
            {
                _connections[sockfd]->Recver();
            }
            if ((events & EPOLLOUT) && IsExist(sockfd))
            {
                _connections[sockfd]->Sender();
            }
        }
    }

public:
    Reactor() : _epoller(std::make_unique<Epoller>())
    {
    }

    void AddConnection(std::shared_ptr<Connection> &conn)
    {
        // conn 插入到 _connections
        if (IsExist(conn))
        {
            LOG(LogLevel::INFO) << conn->Sockfd() << " conn alreadly exit";
            return;
        }
        conn->SetOwner(this);
        _connections.insert({conn->Sockfd(), conn});
        _epoller->AddEvent(conn->Sockfd(), conn->Events()); //
        LOG(LogLevel::INFO) << conn->Sockfd() << " conn add to Reactor";
    }

     void DelConnection(int sockfd)
    {
        if (!IsExist(sockfd))
            return;
        // 1.从 epoll 中删除
        _epoller->DelEvent(sockfd);
        // 2.关闭 fd
        close(sockfd);
        // 3.从映射中移除
        _connections.erase(sockfd);
        LOG(LogLevel::INFO) << sockfd << " conn removed from Reactor";
    }
    void EnableReadWrite(int sockfd, bool enableread, bool enablewrite)
    {
        if (!IsExist(sockfd))
        {
            LOG(LogLevel::INFO) << sockfd << " conn not in Reactor ,bug!";
            return;
        }

        uint32_t events = (enableread ? EPOLLIN : 0) | (enablewrite ? EPOLLOUT : 0) | EPOLLET;
        _connections[sockfd]->SetEvent(events);

        // 设置到内核
        _epoller->ModEvent(_connections[sockfd]->Sockfd(), _connections[sockfd]->Events());

    }

    void EventDispatcher()
    {
        int timeout = -1;
        while (true)
        {
            // 处理事件
            LoopOnce(timeout);

            // 连接管理
            // CheckTimeout();
        }
    }

    ~Reactor()
    {
    }

private:
    std::unordered_map<int, std::shared_ptr<Connection>> _connections;
    std::unique_ptr<Epoller> _epoller; // 对事件的管理

    struct epoll_event revs[size];
};